package com.lianyi.push.share.udpclient;

import android.content.Context;
import android.text.TextUtils;

import com.lianyi.push.share.ConstantValue;
import com.lianyi.push.share.listener.UdpSeiviceToClientMessageListener;
import com.lianyi.push.util.CommonUtils;
import com.lianyi.push.util.LogUtil;
import com.lianyi.push.util.Preconditions;

import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;

/**
 * Created by leilei on 2018/4/8.
 */

public class UdpClient {
    private ExecutorService executorService = Executors.newFixedThreadPool(ConstantValue.TCP_MAX_COUNT);
    private Context mContext;
    private UdpSeiviceToClientMessageListener udpSeiviceToClientMessageListener;

    private UdpClient() {
    }

    public void init(Context context) {
        this.mContext = context;
    }

    private static class SingletonHolder {
        private static final UdpClient INSTANCE = new UdpClient();
    }

    public static UdpClient getInstance() {
        return SingletonHolder.INSTANCE;
    }

    /**
     * 发送udp消息
     *
     * @param msg 发送消息内容
     */
    public void StartUdpClient(final String msg, UdpSeiviceToClientMessageListener listener) {
        Preconditions.checkNotNull(mContext, "UdpClient StartUdpClient Context is Null");
        Preconditions.checkNotNull(listener, "UdpClient StartUdpClient UdpSeiviceToClientMessageListener is Null");
        this.udpSeiviceToClientMessageListener = listener;
        if (CommonUtils.Available(mContext)) {
            if (!TextUtils.isEmpty(msg)) {
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        UdpClient.getInstance().StartClient(msg);
                    }
                });
            }
        }
    }

    public void StartClient(String msg) {
        Preconditions.checkNotNull(msg, "UdpClient StartClient msg is Null");
        Preconditions.checkNotNull(mContext, "UdpClient StartClient mContext is Null");
        Preconditions.checkNotNull(udpSeiviceToClientMessageListener, "UdpClient StartUdpClient udpSeiviceToClientMessageListener is Null");
        if (CommonUtils.Available(mContext)) {
            EventLoopGroup group = null;
            try {
                group = new NioEventLoopGroup();
                Bootstrap b = new Bootstrap();
                b.group(group)
                        .channel(NioDatagramChannel.class)//由于我们用的是UDP协议，所以要用NioDatagramChannel来创建
                        .option(ChannelOption.SO_BROADCAST, true)//支持广播
                        .handler(new UdpClientHandler(udpSeiviceToClientMessageListener));//UdpClientHandler是业务处理类

                Channel ch = b.bind(0).sync().channel();
                // 向网段内所有机器广播发UDP消息
                ch.writeAndFlush(
                        new DatagramPacket(
                                Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8),
                                new InetSocketAddress(
                                        ConstantValue.UDP_HOSTNAME, ConstantValue.UDP_PORT
                                ))).sync();
                if (!ch.closeFuture().await(4000)) {
//                    LogUtil.e("查询超时！！！", "查询超时！！！");
                    ch.close();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
//                try {
                    if (group != null) {
                        group.shutdownGracefully();
                    }
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
            }
        }
    }
}
